package com.lmy.springboot.config;

import com.lmy.springboot.bean.Dog;
import com.lmy.springboot.bean.Furn;
import com.lmy.springboot.bean.Monster;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;

/**
 * 1.configuration 标识这是一个配置类，等价于配置文件(beans.xml)
 * 2.这时就可以通过@Bean注解 注入bean对象到spring容器中(<bean></bean>)
 * 3.配置类本身也会作为bean注入到spring容器中
 * 4.proxyBeanMethods:代理bean的方法 默认是Full
 *   Full(proxyBeanMethods=true)：保证每个@Bean方法被调用多少次返回的组件都是单例的，是代理方式
 *   Lite(proxyBeanMethods=false)：每个@Bean方法被调用多少次返回的组件都是新创建的，是非代理方式
 * 5.proxyBeanMethods 是在调用@Bean方法才生效，因此需要先获取BeanConfig组件在调用方法，而不是直接从Springboot主程序来获取bean
 *   如果直接在主程序 ioc.getBean()，proxyBeanMethods不会生效
 * 6.组件依赖必须使用Full模式默认，如果不需要组件依赖使用Lite模式
 * 7.@EnableConfigurationProperties({Furn.class})
 *   开启Furn配置绑定功能，把Furn组件自动注册到容器中
 */
@Configuration(proxyBeanMethods = false)
@EnableConfigurationProperties({Furn.class})
public class BeanConfig {

    /**
     * 1.@bean 表示给容器添加了一个组件，就是Monster对象
     * 2.monster02() 表示 方法名作为bean的名称/id
     * 3.Monster 注入的bean类型
     * 4.new Monster(200, "蚂蚁", 300, "搬运"); 注入到容器中具体的bean信息
     * 5.name = "monster_nmw" 表示在配置、注入bean时，指定 id为monster_nmw
     * 6.默认是单例
     * 7.@Scope(value = "prototype") 指定该bean是多例，即每次返回新的对象
     * @return
     */
    @Bean(name = "monster_nmw")
//    @Scope(value = "prototype")
    public Monster monster02() {
        return new Monster(200, "蚂蚁", 300, "搬运");
    }

    /**
     * ConditionalOnBean(name = "monsters")
     * 1.表示当容器中有一个bean，名字是monsters，就注入dog01这个Dog bean
     * 2.如果没有monsters，就不注入
     * 3.注解也可以放在配置类，表示对该配置类的所有要注入的组件，都进行条件约束
     * @return
     */
    @Bean
    @ConditionalOnBean(name = "monsters")
    public Dog dog01() {
        return new Dog();
    }

}
